package com.customer.service.Impl;

import cn.xfyun.api.IatClient;
import cn.xfyun.model.response.iat.IatResponse;
import cn.xfyun.model.response.iat.Text;
import cn.xfyun.service.iat.AbstractIatWebSocketListener;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.customer.config.PropertiesConfig;
import com.customer.dto.AITextRequestDTO;
import com.customer.properties.AlProperties;
import com.customer.service.AIService;
import com.customer.service.AISessionService;
import com.customer.vo.AIResponseVO;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Response;
import okhttp3.WebSocket;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.SignatureException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;

import com.customer.model.tts.RelayTTSResponse;
import com.customer.model.tts.TTSRequest;
import org.apache.commons.lang.StringUtils;

import javax.websocket.*;
import java.io.IOException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import javax.websocket.ClientEndpointConfig;

/**
 * AI服务实现类
 */
@Service
@Slf4j
public class AIServiceImpl implements AIService {
    // 七牛云AI服务配置
    private final String QINIU_AI_TTS_WSS_URL;
    private final String QINIU_AI_LLM_API_URL;
    private final String QINIU_AI_TOKEN;
    // 存储会话上下文
    private Map<String, List<Map<String, String>>> sessionContext = new ConcurrentHashMap<>();
    // 构造函数注入
    @Autowired
    public AIServiceImpl(AlProperties alProperties) {
        this.QINIU_AI_TTS_WSS_URL = alProperties.getTts();
        this.QINIU_AI_LLM_API_URL = alProperties.getLlm();
        this.QINIU_AI_TOKEN = alProperties.getToken();
    }

    /**
     * 调用AI服务
     *
     * @param requestDTO 请求参数
     * @return 响应结果
     */
    @Override
    public AIResponseVO callAI(AITextRequestDTO requestDTO) {
        if (requestDTO == null || requestDTO.getText() == null || requestDTO.getText().trim().isEmpty()) {
            log.error("请求参数无效");
            return AIResponseVO.builder().isCompleted(false).build();
        }

        String sessionId = requestDTO.getSessionId();
        if (sessionId == null || sessionId.isEmpty()) {
            sessionId = UUID.randomUUID().toString();
        }

        try {
            // 获取或创建会话上下文
            List<Map<String, String>> messages = sessionContext.computeIfAbsent(sessionId, k -> new ArrayList<>());

            // 添加用户消息到上下文
            Map<String, String> userMessage = new HashMap<>();
            userMessage.put("role", "user");
            userMessage.put("content", requestDTO.getText());
            messages.add(userMessage);

            // 调用七牛云AI服务
            String responseText = callQiniuAIService(messages);

            // 添加AI回复到上下文
            Map<String, String> assistantMessage = new HashMap<>();
            assistantMessage.put("role", "assistant");
            assistantMessage.put("content", responseText);
            messages.add(assistantMessage);

            // 构建响应
            return AIResponseVO.builder()
                    .text(responseText)
                    .sessionId(sessionId)
                    .isCompleted(true)
                    .build();
        } catch (Exception e) {
            log.error("调用AI服务失败: {}", e.getMessage(), e);
            return AIResponseVO.builder()
                    .text("抱歉，服务暂时不可用，请稍后再试")
                    .sessionId(sessionId)
                    .isCompleted(false)
                    .build();
        }
    }

    /**
     * 调用七牛云AI服务
     *
     * @param messages 消息列表
     * @return AI响应文本
     */
    private String callQiniuAIService(List<Map<String, String>> messages) throws Exception {
        StringBuilder fullResponse = new StringBuilder();

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(QINIU_AI_LLM_API_URL);

            // 设置请求头
            httpPost.setHeader("Content-Type", "application/json");
            httpPost.setHeader("Authorization", "Bearer " + QINIU_AI_TOKEN);

            // 构建请求体
            JSONObject requestBody = new JSONObject();
            requestBody.put("model", "deepseek-v3");
            requestBody.put("messages", messages);
            requestBody.put("stream", true);
            requestBody.put("max_tokens", 4096);

            // 设置请求体
            StringEntity entity = new StringEntity(requestBody.toString(), StandardCharsets.UTF_8);
            httpPost.setEntity(entity);

            // 执行请求
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                HttpEntity responseEntity = response.getEntity();
                if (responseEntity != null) {
                    // 处理流式响应
                    try (BufferedReader reader = new BufferedReader(
                            new InputStreamReader(responseEntity.getContent(), StandardCharsets.UTF_8))) {
                        String line;
                        while ((line = reader.readLine()) != null) {
                            // 处理SSE格式的响应
                            if (line.startsWith("data: ")) {
                                String data = line.substring(6);
                                if (data.equals("[DONE]")) {
                                    break;
                                }

                                try {
                                    JSONObject json = JSON.parseObject(data);
                                    JSONArray choices = json.getJSONArray("choices");
                                    if (choices != null && !choices.isEmpty()) {
                                        JSONObject choice = choices.getJSONObject(0);
                                        JSONObject delta = choice.getJSONObject("delta");
                                        if (delta.containsKey("content")) {
                                            fullResponse.append(delta.getString("content"));
                                        }
                                    }
                                } catch (Exception e) {
                                    log.warn("解析响应行失败: {}", line, e);
                                }
                            }
                        }
                    }
                }
            }
        }

        return fullResponse.toString();
    }

    /**
     * 七牛云TTS服务
     *
     * @param text      文本内容
     * @param voiceType 声音类型
     * @return 音频数据（Base64编码）
     */
    @Override
    public String doTTS(String text, String voiceType) {
        if (text == null || text.trim().isEmpty()) {
            log.error("TTS文本内容为空");
            return null;
        }

        // 如果未指定音色，使用默认音色
        if (StringUtils.isEmpty(voiceType)) {
            voiceType = "qiniu_zh_female_tmjxxy";
        }

        try {
            log.info("开始TTS转换，文本长度: {}, 音色: {}", text.length(), voiceType);
            return streamTTS(text, voiceType);
        } catch (Exception e) {
            log.error("TTS转换失败: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 流式TTS合成
     *
     * @param text      文本内容
     * @param voiceType 音色类型
     * @return Base64编码的音频数据
     */
    private String streamTTS(String text, String voiceType) throws Exception {
        CountDownLatch latch = new CountDownLatch(1);
        AtomicReference<byte[]> audioDataRef = new AtomicReference<>(new byte[0]);
        AtomicReference<Exception> exceptionRef = new AtomicReference<>();

        // 创建WebSocket客户端
        WebSocketContainer container = ContainerProvider.getWebSocketContainer();
        // 增加消息大小限制
        container.setDefaultMaxTextMessageBufferSize(1024 * 1024 * 5); // 5MB
        container.setDefaultMaxBinaryMessageBufferSize(1024 * 1024 * 5); // 5MB
        URI uri = new URI(QINIU_AI_TTS_WSS_URL);

        // 创建客户端配置，用于设置请求头
        ClientEndpointConfig config = ClientEndpointConfig.Builder.create()
                .configurator(new ClientEndpointConfig.Configurator() {
                    @Override
                    public void beforeRequest(Map<String, List<String>> headers) {
                        headers.put("Authorization", Collections.singletonList("Bearer " + QINIU_AI_TOKEN));
                        headers.put("VoiceType", Collections.singletonList(voiceType));
                    }
                })
                .build();

        // 修改文本消息处理器的创建方式
        MessageHandler.Whole<String> textMessageHandler = new MessageHandler.Whole<String>() {
            @Override
            public void onMessage(String message) {
                try {
                    // 解析响应
                    RelayTTSResponse response = JSON.parseObject(message, RelayTTSResponse.class);

                    // 解码音频数据
                    byte[] decodedData = Base64.getDecoder().decode(response.getData());

                    // 追加到总音频数据
                    byte[] currentAudio = audioDataRef.get();
                    byte[] newAudio = new byte[currentAudio.length + decodedData.length];
                    System.arraycopy(currentAudio, 0, newAudio, 0, currentAudio.length);
                    System.arraycopy(decodedData, 0, newAudio, currentAudio.length, decodedData.length);
                    audioDataRef.set(newAudio);

                    // 检查是否为最后一包数据
                    if (response.getSequence() < 0) {
                        log.info("TTS合成完成，音频数据长度: {}", newAudio.length);
                        latch.countDown();
                    }
                } catch (Exception e) {
                    log.error("处理TTS响应失败", e);
                    exceptionRef.set(e);
                    latch.countDown();
                }
            }
        };

        // 修改二进制消息处理器的创建方式
        MessageHandler.Whole<ByteBuffer> binaryMessageHandler = new MessageHandler.Whole<ByteBuffer>() {
            @Override
            public void onMessage(ByteBuffer message) {
                try {
                    byte[] binaryData = new byte[message.remaining()];
                    message.get(binaryData);
                    String messageStr = new String(binaryData, "UTF-8");
                    textMessageHandler.onMessage(messageStr);
                } catch (Exception e) {
                    log.error("处理TTS二进制响应失败", e);
                    exceptionRef.set(e);
                    latch.countDown();
                }
            }
        };

        // 连接WebSocket服务器
        Session session = container.connectToServer(new Endpoint() {
            @Override
            public void onOpen(Session session, EndpointConfig config) {
                try {
                    // 注册消息处理器
                    session.addMessageHandler(textMessageHandler);
                    session.addMessageHandler(binaryMessageHandler);

                    // 构建请求参数
                    TTSRequest request = new TTSRequest();
                    TTSRequest.Audio audio = new TTSRequest.Audio();
                    audio.setVoice_type(voiceType);
                    audio.setEncoding("mp3");
                    audio.setSpeed_ratio(1.0);

                    TTSRequest.Request req = new TTSRequest.Request();
                    req.setText(text);

                    request.setAudio(audio);
                    request.setRequest(req);

                    // 发送请求
                    String requestJson = JSON.toJSONString(request);
                    session.getBasicRemote().sendText(requestJson);
                    log.info("TTS请求已发送");
                } catch (IOException e) {
                    log.error("发送TTS请求失败", e);
                    exceptionRef.set(e);
                    latch.countDown();
                }
            }

            @Override
            public void onClose(Session session, CloseReason closeReason) {
                log.info("TTS WebSocket连接已关闭: {}", closeReason.getReasonPhrase());
                // 修改这里：只要连接关闭且latch尚未触发，就触发latch
                if (latch.getCount() > 0) {
                    // 如果是异常关闭，设置异常信息
                    if (closeReason.getCloseCode() != CloseReason.CloseCodes.NORMAL_CLOSURE) {
                        exceptionRef.set(new IOException("WebSocket连接异常关闭: " + closeReason.getReasonPhrase()));
                    }
                    latch.countDown();
                }
            }

            @Override
            public void onError(Session session, Throwable throwable) {
                log.error("TTS WebSocket连接异常", throwable);
                exceptionRef.set(new Exception(throwable));
                if (latch.getCount() > 0) {
                    latch.countDown();
                }
            }
        }, config, uri);

        try {
            // 等待TTS合成完成或超时
            boolean completed = latch.await(30, TimeUnit.SECONDS);

            // 检查是否有异常
            Exception exception = exceptionRef.get();
            if (exception != null) {
                throw exception;
            }

            if (!completed) {
                throw new IOException("TTS合成超时");
            }

            // 返回Base64编码的音频数据
            return Base64.getEncoder().encodeToString(audioDataRef.get());
        } finally {
            // 确保关闭连接
            if (session != null && session.isOpen()) {
                try {
                    session.close();
                } catch (IOException e) {
                    log.warn("关闭TTS WebSocket连接失败", e);
                }
            }
        }
    }


    /**
     * 通过文件路径进行ASR识别
     *
     * @param audioFilePath 音频文件路径
     * @return 识别后的文本内容
     */
    @Override
    public String doASRByFilePath(String audioFilePath) throws Exception {
        if (audioFilePath == null || audioFilePath.trim().isEmpty()) {
            log.error("ASR音频文件路径为空");
            return null;
        }

        File audioFile = new File(audioFilePath);
        if (!audioFile.exists() || !audioFile.isFile()) {
            log.error("音频文件不存在或不是有效文件: {}", audioFilePath);
            throw new FileNotFoundException("音频文件不存在: " + audioFilePath);
        }

        log.info("开始ASR转换(文件方式)，文件路径: {}, 文件大小: {}字节",
                audioFilePath, audioFile.length());

        // 使用讯飞SDK进行语音识别，参考官方Demo
        return xfyunASRByFile(audioFile);
    }

    /**
     * 使用讯飞SDK通过文件进行语音识别
     */
    private String xfyunASRByFile(File audioFile) throws Exception {
        // 文件有效性检查
        if (audioFile == null || !audioFile.exists() || !audioFile.isFile()) {
            log.error("音频文件不存在或无效: {}", audioFile != null ? audioFile.getAbsolutePath() : "null");
            throw new IllegalArgumentException("音频文件不存在或无效");
        }

        if (audioFile.length() == 0) {
            log.error("音频文件为空: {}", audioFile.getAbsolutePath());
            throw new IllegalArgumentException("音频文件为空");
        }

        // 创建讯飞语音听写客户端
        IatClient iatClient = new IatClient.Builder()
                .signature(PropertiesConfig.getAppId(), PropertiesConfig.getApiKey(), PropertiesConfig.getApiSecret())
                // 动态修正功能：值为wpgs时代表开启（包含修正功能的）流式听写
                .dwa("wpgs")
                .vad_eos(6000)
                .build();

        // 用于等待识别结果的同步锁
        CountDownLatch countDownLatch = new CountDownLatch(1);
        List<Text> resultSegments = new ArrayList<>(); // 用于存储识别片段
        final String[] finalResult = {""};
        Date dateBegin = new Date();

        try {
            // 直接发送PCM文件进行识别
            log.info("开始发送PCM文件进行识别: {}", audioFile.getAbsolutePath());
            iatClient.send(audioFile, new AbstractIatWebSocketListener() {
                @Override
                public void onSuccess(WebSocket webSocket, IatResponse iatResponse) {
                    log.info("接收到讯飞ASR响应: code={}, message={}, sid={}",
                            iatResponse.getCode(), iatResponse.getMessage(), iatResponse.getSid());

                    if (iatResponse.getCode() != 0) {
                        log.warn("讯飞ASR错误：code：{}, error：{}, sid：{}",
                                iatResponse.getCode(), iatResponse.getMessage(), iatResponse.getSid());
                        log.warn("错误码查询链接：https://www.xfyun.cn/document/error-code");
                        countDownLatch.countDown();
                        return;
                    }

                    if (iatResponse.getData() != null) {
                        if (iatResponse.getData().getResult() != null) {
                            // 解析服务端返回结果
                            Text textObject = iatResponse.getData().getResult().getText();
                            handleResultText(textObject, resultSegments);
                            String currentResult = getFinalResult(resultSegments);
                            log.info("中间识别结果：{}", currentResult);
                        }

                        if (iatResponse.getData().getStatus() == 2) {
                            // resp.data.status ==2 说明数据全部返回完毕
                            finalResult[0] = getFinalResult(resultSegments);
                            Date dateEnd = new Date();
                            log.info("识别开始时间：{}, 识别结束时间：{}, 总耗时：{}ms",
                                    new SimpleDateFormat("yyy-MM-dd HH:mm:ss.SSS").format(dateBegin),
                                    new SimpleDateFormat("yyy-MM-dd HH:mm:ss.SSS").format(dateEnd),
                                    dateEnd.getTime() - dateBegin.getTime());
                            log.info("最终识别结果：【{}】，本次识别sid：{}",
                                    finalResult[0], iatResponse.getSid());
                            countDownLatch.countDown();
                        }
                    }
                }

                @Override
                public void onFail(WebSocket webSocket, Throwable t, Response response) {
                    log.error("讯飞ASR连接失败", t);
                    countDownLatch.countDown();
                }
            });

            // 等待识别完成，最多等待60秒
            boolean awaitResult = countDownLatch.await(60, TimeUnit.SECONDS);
            if (!awaitResult) {
                log.error("讯飞ASR识别超时");
                return null;
            }

            log.info("讯飞ASR识别成功，最终结果长度: {}", finalResult[0].length());
            return finalResult[0];
        } catch (SignatureException e) {
            log.error("讯飞API签名验证失败", e);
            throw new RuntimeException("讯飞服务鉴权异常，请检查密钥配置", e);
        } catch (IOException e) {
            log.error("讯飞音频流操作异常", e);
            throw new RuntimeException("讯飞音频数据传输失败", e);
        } finally {
            try {
                iatClient.closeWebsocket();
            } catch (Exception e) {
                log.warn("关闭讯飞WebSocket连接异常", e);
            }
        }
    }

    /**
     * 基于讯飞实现执行ASR转换
     *
     * @param audioData  音频数据
     * @param format     音频格式
     * @param sampleRate 音频采样率
     * @return 识别后的文本内容
     */
    @Override
    public String doASRByData(byte[] audioData, String format, Integer sampleRate) throws Exception {
        if (audioData == null || audioData.length == 0) {
            log.error("ASR音频数据为空");
            return null;
        }

        // 检查音频数据是否有效（非静默）
        boolean hasContent = isAudioDataValid(audioData);
        log.info("开始ASR转换(数据方式)，数据长度: {}字节, 格式: {}, 采样率: {}, 包含有效内容: {}",
                audioData.length, format, sampleRate, hasContent);

        // 使用讯飞SDK进行语音识别
        return xfyunASRByData(audioData, format, sampleRate);
    }

    /**
     * 检查音频数据是否有效（非静默）
     */
    private boolean isAudioDataValid(byte[] audioData) {
        // 增强的音频有效性检测算法
        if (audioData == null || audioData.length < 1000) { // 设置最小长度阈值
            return false;
        }

        // 统计非零字节数和非零字节比例
        int nonZeroCount = 0;
        for (byte b : audioData) {
            if (Math.abs(b) > 10) { // 设置更严格的阈值
                nonZeroCount++;
            }
        }

        // 计算非零字节比例，必须超过10%才认为有效
        double nonZeroRatio = (double) nonZeroCount / audioData.length;
        log.info("音频数据检测: 总长度={}字节, 非零字节数={}, 比例={}",
                audioData.length, nonZeroCount, nonZeroRatio);

        return nonZeroRatio > 0.1;
    }

    /**
     * 使用讯飞SDK进行语音识别
     */
    private String xfyunASRByData(byte[] audioData, String format, Integer sampleRate) throws Exception {
        // 增强的音频数据质量验证
        boolean hasContent = isAudioDataValid(audioData);
        if (!hasContent) {
            log.warn("音频数据无效或为静默，跳过识别");
            return "[静默或无效音频]";
        }

        // 创建讯飞语音听写客户端
        IatClient iatClient = new IatClient.Builder()
                .signature(PropertiesConfig.getAppId(), PropertiesConfig.getApiKey(), PropertiesConfig.getApiSecret())
                .dwa("wpgs")
                .vad_eos(6000)
                // 添加更多必要参数
                //                .lang("zh_cn")  // 设置中文识别
                .accent("mandarin") // 设置普通话
                .ptt(0) // 关闭标点符号
                .build();

        // 其余代码保持不变
        // 用于等待识别结果的同步锁
        CountDownLatch countDownLatch = new CountDownLatch(1);
        List<Text> resultSegments = new ArrayList<>(); // 用于存储识别片段
        final String[] finalResult = {""};

        try {
            // 使用管道流模拟官方Demo的音频流处理方式
            PipedInputStream audioInputStream = new PipedInputStream();
            PipedOutputStream audioOutputStream = new PipedOutputStream(audioInputStream);

            // 创建并启动一个线程来写入音频数据，模拟实时音频流
            Thread audioSenderThread = new Thread(() -> {
                try {
                    log.info("开始向管道流写入音频数据，总长度: {}", audioData.length);
                    // 分批写入音频数据，每批4096字节，更接近实时音频流
                    int batchSize = 4096;
                    for (int i = 0; i < audioData.length; i += batchSize) {
                        int currentBatchSize = Math.min(batchSize, audioData.length - i);
                        audioOutputStream.write(audioData, i, currentBatchSize);
                        // 模拟实时音频流的间隔
                        Thread.sleep(20);
                    }
                    log.info("音频数据写入完成");
                    audioOutputStream.flush();
                    audioOutputStream.close();
                } catch (Exception e) {
                    log.error("写入音频数据异常: {}", e.getMessage(), e);
                }
            });
            audioSenderThread.start();

            // 发送音频数据并处理识别结果
            iatClient.send(audioInputStream, new AbstractIatWebSocketListener() {
                @Override
                public void onSuccess(WebSocket webSocket, IatResponse iatResponse) {
                    log.info("接收到讯飞ASR响应: code={}, message={}, sid={}",
                            iatResponse.getCode(), iatResponse.getMessage(), iatResponse.getSid());

                    if (iatResponse.getCode() != 0) {
                        log.warn("讯飞ASR错误：code：{}, error：{}, sid：{}",
                                iatResponse.getCode(), iatResponse.getMessage(), iatResponse.getSid());
                        countDownLatch.countDown();
                        return;
                    }

                    if (iatResponse.getData() != null) {
                        log.info("讯飞ASR响应数据：status={}, result={}",
                                iatResponse.getData().getStatus(),
                                iatResponse.getData().getResult() != null ? iatResponse.getData().getResult().getText() : "null");

                        if (iatResponse.getData().getResult() != null && iatResponse.getData().getResult().getText() != null) {
                            // 使用handleResultText处理识别结果
                            Text textObject = iatResponse.getData().getResult().getText();
                            log.debug("讯飞ASR文本对象详情: text='{}', pgs={}, sn={}, ls={}, deleted={}",
                                    textObject.getText(), textObject.getPgs(), textObject.getSn(),
                                    textObject.isLs(), textObject.isDeleted());

                            handleResultText(textObject, resultSegments);
                            String currentResult = getFinalResult(resultSegments);
                            log.info("当前识别片段数: {}, 当前累积结果: {}, 长度: {}",
                                    resultSegments.size(), currentResult.isEmpty() ? "[空]" : currentResult, currentResult.length());
                        }

                        if (iatResponse.getData().getStatus() == 2) {
                            // 数据全部返回完毕
                            finalResult[0] = getFinalResult(resultSegments);
                            log.info("讯飞ASR识别完成，总片段数: {}, 总结果长度: {}",
                                    resultSegments.size(), finalResult[0].length());
                            countDownLatch.countDown();
                        }
                    }
                }

                @Override
                public void onFail(WebSocket webSocket, Throwable t, Response response) {
                    log.error("讯飞ASR连接失败", t);
                    countDownLatch.countDown();
                }
            });

            // 等待识别完成，最多等待60秒
            boolean awaitResult = countDownLatch.await(60, TimeUnit.SECONDS);
            if (!awaitResult) {
                log.error("讯飞ASR识别超时");
                return null;
            }

            log.info("讯飞ASR识别成功，最终结果长度: {}", finalResult[0].length());
            return finalResult[0];
        } catch (SignatureException e) {
            log.error("讯飞API签名验证失败", e);
            throw new RuntimeException("讯飞服务鉴权异常，请检查密钥配置", e);
        } catch (IOException e) {
            log.error("讯飞音频流操作异常", e);
            throw new RuntimeException("讯飞音频数据传输失败", e);
        } finally {
            try {
                iatClient.closeWebsocket();
            } catch (Exception e) {
                log.warn("关闭讯飞WebSocket连接异常", e);
            }
        }
    }

    /**
     * 处理返回结果（包括全量返回与流式返回）
     */
    private void handleResultText(Text textObject, List<Text> resultSegments) {
        // 增强日志，记录每个识别片段的详细信息
        log.info("处理识别片段: sn={}, text='{}', pgs={}, deleted={}",
                textObject.getSn(), textObject.getText(), textObject.getPgs(), textObject.isDeleted());

        // 处理流式返回的替换结果
        if (StringUtils.equals(textObject.getPgs(), "rpl") && textObject.getRg() != null && textObject.getRg().length == 2) {
            int start = Math.max(0, textObject.getRg()[0] - 1);
            int end = Math.min(resultSegments.size() - 1, textObject.getRg()[1] - 1);

            // 将指定区间的结果设置为删除状态
            for (int i = start; i <= end; i++) {
                resultSegments.get(i).setDeleted(true);
            }
        }

        // 通用逻辑，添加当前文本到结果列表
        resultSegments.add(textObject);
    }

    /**
     * 获取最终结果
     */
    private String getFinalResult(List<Text> resultSegments) {
        StringBuilder finalResult = new StringBuilder();
        for (Text text : resultSegments) {
            if (text != null && !text.isDeleted()) {
                finalResult.append(text.getText());
            }
        }
        return finalResult.toString();
    }

    /**
     * URL模式下的ASR转换
     *
     * @param audioUrl   音频URL
     * @param format     音频格式
     * @param sampleRate 采样率
     * @return 转换后的文本结果
     */
    @Override
    public String doASRByUrl(String audioUrl, String format, Integer sampleRate) {
        if (audioUrl == null || audioUrl.trim().isEmpty()) {
            log.error("ASR音频URL为空");
            return null;
        }

        // 修改doASRByUrl方法中的URL清理逻辑
        audioUrl = audioUrl.replaceAll("[`',\\s]", "").trim();

        // 设置默认值
        if (format == null || format.trim().isEmpty()) {
            format = "mp3";
        }
        if (sampleRate == null || sampleRate <= 0) {
            sampleRate = 16000;
        }

        try {
            log.info("开始ASR转换(URL方式)，音频URL: {}, 格式: {}, 采样率: {}", audioUrl, format, sampleRate);

            // 使用HTTP POST请求，而不是WebSocket
            return httpASRByUrl(audioUrl, format, sampleRate);
        } catch (Exception e) {
            log.error("ASR转换(URL方式)失败: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 使用HTTP请求方式调用ASR服务
     */
    private String httpASRByUrl(String audioUrl, String format, Integer sampleRate) throws Exception {
        // 创建HTTP客户端
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            // 构建HTTP POST请求 - 使用正确的七牛云ASR API地址
            HttpPost httpPost = new HttpPost("https://openai.qiniu.com/v1/voice/asr");

            // 设置请求头
            httpPost.setHeader("Content-Type", "application/json");
            httpPost.setHeader("Authorization", "Bearer " + QINIU_AI_TOKEN);

            // 构建请求体，严格按照官方文档格式
            JSONObject requestBody = new JSONObject();
            requestBody.put("model", "asr");

            // 创建audio对象并设置音频参数
            JSONObject audioObject = new JSONObject();
            audioObject.put("format", format);
            audioObject.put("url", audioUrl);

            // 将audio对象添加到请求体
            requestBody.put("audio", audioObject);

            // 设置请求体
            StringEntity entity = new StringEntity(requestBody.toString(), StandardCharsets.UTF_8);
            httpPost.setEntity(entity);

            log.info("ASR HTTP请求已发送: {}", requestBody.toString());

            // 执行请求
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                HttpEntity responseEntity = response.getEntity();
                if (responseEntity != null) {
                    String responseText = EntityUtils.toString(responseEntity);
                    log.info("ASR HTTP响应: {}", responseText);

                    // 解析响应结果
                    return parseHttpASRResponse(responseText);
                }
            }
        }
        return null;
    }

    /**
     * 解析HTTP ASR响应
     */
    private String parseHttpASRResponse(String responseText) {
        try {
            // 首先检查响应是否为空或明显不是JSON
            if (responseText == null || responseText.trim().isEmpty() ||
                    !responseText.trim().startsWith("{") || !responseText.trim().endsWith("}")) {
                log.error("无效的ASR响应格式: {}", responseText);
                return null;
            }

            JSONObject response = JSON.parseObject(responseText);

            // 检查响应状态
            if (response.containsKey("code") && response.getInteger("code") != 0) {
                log.error("ASR服务返回错误: {}, 消息: {}",
                        response.getInteger("code"),
                        response.getString("message"));
                return null;
            }

            // 提取识别结果 - 适配官方文档中的响应结构
            if (response.containsKey("data")) {
                JSONObject data = response.getJSONObject("data");
                // 检查第一种格式: data.audio_asr.result/text
                if (data.containsKey("audio_asr")) {
                    JSONObject asrResult = data.getJSONObject("audio_asr");
                    if (asrResult.containsKey("result")) {
                        return asrResult.getString("result");
                    } else if (asrResult.containsKey("text")) {
                        return asrResult.getString("text");
                    }
                }
                // 检查第二种格式: data.result.text
                else if (data.containsKey("result")) {
                    JSONObject resultData = data.getJSONObject("result");
                    if (resultData.containsKey("text")) {
                        return resultData.getString("text");
                    } else if (resultData.containsKey("result")) {
                        return resultData.getString("result");
                    }
                }
            } else if (response.containsKey("result")) {
                return response.getString("result");
            } else if (response.containsKey("text")) {
                return response.getString("text");
            }

            log.warn("未在ASR响应中找到识别结果: {}", responseText);
            return null;
        } catch (Exception e) {
            log.error("解析ASR HTTP响应失败", e);
            return null;
        }
    }
}

